<template>
  <div>
    <div class="main-frame-desktop-header">
      <div class="top-section" 
      style="display: flex; align-items: center; justify-content: space-between; padding: 12px 12px;">
        <div class="header-wrapper">
          <h3 class="title">酒店周预测环比分析</h3>
        </div>
        <div class="form-wrapper" style="margin-bottom: 0; display: flex; align-items: center; gap: 8px;"> 
          <div class="form-content" style="display: flex; align-items: center; gap: 8px;">
            <div class="form-item">
              
              <a-date-picker v-model:value="currentMonth" picker="month" :allowClear="false" valueFormat="YYYY-MM" />
            </div>
            <div class="form-item form-item-center">
              <span class="label">周</span>
              <a-select v-model:value="currentWeek" :options="weekList" :allowClear="false" />
            </div>
            <!-- <div class="form-item form-item-center">
              <span class="label">展示详细列</span>
              <a-switch v-model:checked="isDetail" />
            </div> -->
            <div class="form-item">
              <a-button type="primary" @click="handleSearch">查询</a-button>
              <a-button style="margin-left: 8px" @click="handleReset">重置</a-button>
              <div class="filter-icon-container">
                <img class="icon-screen" src="/@/assets/images/screening.png" @click="handleShowFilter" alt="筛选图标" :title="'过滤设置'" />
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="main-content">
      <TableCard
        class="card-flex-all"
        title="周预测环比分析"
        :dataList="dataList"
        :columns="getDataColumns()"
        :scroll="tableHigh"
        :exportData="dataList"
        :loading="loading"
        :summary="summaryData"
        :exportHeader="getExportHeader()"
        :exprotMerges="getExprotMerges()"
      >
        <template #hotelName="{ text }">
          <span v-if="checkTag(text)" class="main-content-title-custom">{{ text }}</span>
          <span v-else>{{ text }}</span>
        </template>
      </TableCard>
    </div>
  </div>
  <SearchFilterModal v-if="showFilter" v-model:visible="showFilter" :fields="searchFormOptions" :visible="showFilter" @save="handleSaveFilter" />
</template>

<script>
  import dayjs from 'dayjs';
  import { defHttp } from '/@/utils/http/axios';
  import * as MathUtil from '/@/utils/MathUtil';
  import * as DateUtil from '/@/utils/dateUtil';
  import SearchFilterModal from '/@/views/applications/ui/SearchFilterModal.vue';
  import TableCard from '/@/views/applications/ui/TableCard.vue';

  const VALUE_KEYS = [
    { prefix: 'p', valueKey: 'preFvalue' },
    { prefix: 'b', valueKey: 'budgetFvalue' },
    { prefix: 'a', valueKey: 'actualFvalue' },
  ];
  export default {
    name: 'HotelWeekPreQoq',
    components: {
      TableCard,
      SearchFilterModal,
    },
    data() {
      return {
        loading: false,
        currentMonth: dayjs(),
        currentWeek: this.getWeekOfMonth(dayjs()),
        hotelList: [],
        currentCode: '',
        subjectList: [],
        dataList: [],
        weekList: DateUtil.generateWeekList().map((w) => ({
          label: `第${w}周`,
          value: w,
        })),
        tableHigh: { x: '100%', y: 'calc(60vh)' },
        sumKeys: [],
        colKeys: ['hotelCode', 'hotelName'],
        dataColumns: [],
        isDetail: false,
        showFilter: false,
        searchFormOptions: [
          {
            value: 'date',
            label: '预测月份',
            selected: true,
            showDetails: true,
          },
          {
            value: 'week',
            label: '周',
            selected: true,
            showDetails: true,
          },
          // {
          //   value: 'detail',
          //   label: '展示详细列',
          //   selected: true,
          //   showDetails: true
          // }
        ],
        exportHeader: [],
        showSubject: [],
      };
    },

    created() {
      Promise.all([
        defHttp.get({ url: '/data/hotel/list' }, { isTransformResponse: false }),
        defHttp.post({
          url: '/data/query',
          data: {
            labelCode: 'getHotelPresubject',
            sqlParams: [],
            pageIndex: 1,
            pageSize: 100,
          },
        }),
      ]).then(([res1, res2]) => {
        if (res1.code === 200 && res1.result.length > 0) {
          this.hotelList = res1.result;
          this.currentCode = res1.result.map((d) => d.code).join(',');
        }
        if (res2.datas.success && res2.datas.totalCount > 0) {
          const data2 = res2.datas.data;
          this.subjectList = data2.filter((s) => s.name.includes('收入'));
          VALUE_KEYS.forEach((k) => {
            this.subjectList.forEach((s) => {
              this.colKeys.push(`${k.prefix}${s.code}`);
              if (s.calMode === 'DEFAULT') {
                this.sumKeys.push(`${k.prefix}${s.code}`);
              }
            });
          });
          this.dataColumns = this.getDataColumns();
        }
        this.fetchBaseInfo();
      });
    },

    methods: {
      getWeekOfMonth(date) {
        const startOfMonth = date.clone().startOf('month');
        return date.diff(startOfMonth, 'weeks') + 1;
      },
      fetchBaseInfo() {
        this.loading = true;
        defHttp
          .post({
            url: '/data/query',
            data: {
              labelCode: 'getHotelMonthPreQoq',
              sqlParams: [
                {
                  key: 'code',
                  value: this.currentCode,
                },
                {
                  key: 'month',
                  value: dayjs(this.currentMonth).format('YYYYMM'),
                },
                {
                  key: 'week',
                  value: this.currentWeek,
                },
              ],
              pageIndex: 1,
              pageSize: 5000,
            },
          })
          .then((res) => {
            if (res.datas.success && res.datas.totalCount > 0) {
              const incomeList = res.datas.data;
              const hotelData = this.hotelList.map((h) => {
                let d = {
                  hotelCode: h.code,
                  hotelName: h.name,
                };
                VALUE_KEYS.forEach((k) => {
                  this.subjectList.forEach((s) => {
                    d[`${k.prefix}${s.code}`] = '';
                    if (s.calMode === 'DEFAULT') {
                      incomeList.forEach((i) => {
                        if (i.subjectCode === s.code && i.hotelCode === h.code) {
                          d[`${k.prefix}${s.code}`] = Math.round(i[k.valueKey]) || 0;
                        }
                      });
                    }
                  });
                });
                this.wrapData(d);
                return d;
              });

              const hotelMap = this.hotelList.reduce((acc, hotel) => {
                if (incomeList.filter((d) => d.hotelCode === hotel.code).length > 0) {
                  const key = hotel.hpositionName;
                  if (!acc[key]) {
                    acc[key] = [];
                  }
                  acc[key] = acc[key].concat(hotelData.filter((d) => d.hotelCode === hotel.code));
                }
                return acc;
              }, {});

              let dataList = [];
              Object.keys(hotelMap).forEach((key) => {
                const pDataList = hotelMap[key];
                dataList = dataList.concat(pDataList);
                // 动态生成初始值对象
                const initialTotals = this.colKeys
                  .filter((c) => c !== 'hotelName')
                  .reduce(
                    (acc, field) => {
                      acc[field] = 0;
                      return acc;
                    },
                    { hotelName: `${key}酒店小计` }
                  );

                const subSum = pDataList.reduce((acc, hotel) => {
                  this.sumKeys.forEach((field) => {
                    acc[field] += Number(hotel[field]);
                  });
                  return acc;
                }, initialTotals);
                this.wrapData(subSum);
                dataList.push(subSum);
              });
              this.dataList = dataList;
            } else {
              this.dataList = [];
            }
            this.loading = false;
          });
      },

      wrapData(data) {
        VALUE_KEYS.forEach((k) => {
          this.subjectList
            .filter((s) => s.calMode === 'AUTO')
            .forEach((s) => {
              Object.keys(data)
                .filter((d) => d === `${k.prefix}${s.code}`)
                .forEach((d) => {
                  const replacedFormula = s.formula.replace(/#\{(\d+)\}/g, (_, code) => data[`${k.prefix}${code}`] || 0);
                  data[d] = eval(replacedFormula) || 0;
                });
            });
        });
        // this.subjectList.forEach(s => {
        //   data[`c${s.code}`] = this.percent2DFormatter(
        //     this.safeDivide(data[`p${s.code}`], data[`b${s.code}`]),
        //     0
        //   );
        // });
        this.subjectList.forEach((s) => {
          data[`d${s.code}`] = this.diffPercent2Formatter(data[`p${s.code}`], data[`a${s.code}`], 0);
        });
      },

      summaryData() {
        const initialTotals = this.colKeys
          .filter((c) => c !== 'hotelName' && c !== 'hotelCode')
          .reduce(
            (acc, field) => {
              acc[field] = 0;
              return acc;
            },
            { hotelName: '合计' }
          );
        const d = this.dataList
          .filter((d) => d.hotelName.includes('小计'))
          .reduce((sum, item) => {
            this.sumKeys.forEach((field) => {
              sum[field] += Number(item[field]);
            });
            return sum;
          }, initialTotals);
        this.customRenderData(d, this.dataColumns);
        this.wrapData(d);
        return [d];
      },

      customRenderData(data, columns) {
        columns.forEach((c) => {
          if (c.customRender) {
            const value = { text: data[c.dataIndex] };
            data[c.dataIndex] = c.customRender(value);
          }
          if (c.children) {
            this.customRenderData(data, c.children);
          }
        });
      },

      getDataColumns() {
        let dataColumns = [
          {
            title: '项目名称',
            dataIndex: 'hotelName',
            key: 'hotelName',
            width: 220,
            align: 'left',
            ellipsis: true,
            fixed: 'left',
            scopedSlots: {
              customRender: 'hotelName',
            },
          },
        ];
        const colKeys = [
          { prefix: 'c', title: '本周月度预测' },
          { prefix: 'l', title: '上周月度预测' },
          { prefix: 'd', title: '差异' },
        ];

        colKeys.forEach((c, ci) => {
          dataColumns = dataColumns.concat(
            this.subjectList.map((m, index) => {
              return {
                dataIndex: `${c.prefix}${m.code}`,
                width: index === 2 ? 180 : 130,
                align: 'right',
                className: ci % 2 === 0 ? '' : 'table-header-color',
                title: index === 2 ? `${c.title}` : '',
                children: [
                  {
                    title: m.name,
                    dataIndex: `${c.prefix}${m.code}`,
                    key: `${c.prefix}${m.code}`,
                    width: index === 2 ? 180 : 130,
                    align: 'right',
                    className: ci % 2 === 0 ? '' : 'table-header-color',
                    customRender: (val) => (['d'].includes(c.prefix) ? val.text : this.colRender(val.text, val.record, m)),
                  },
                ],
              };
            })
          );
        });
        return dataColumns;
      },

      getExportHeader() {
        let exportHeader = this.exportHeader;
        exportHeader = [this.getDataColumns().map((c) => c.title), this.getDataColumns().map((c) => (c.children ? c.children[0].title : null))];
        exportHeader[0][1] = exportHeader[0][this.isDetail ? 5 : 2];
        exportHeader[0][this.isDetail ? 11 : 4] = exportHeader[0][this.isDetail ? 15 : 5];
        exportHeader[0][this.isDetail ? 21 : 7] = exportHeader[0][this.isDetail ? 25 : 8];
        exportHeader[0][this.isDetail ? 31 : 10] = exportHeader[0][this.isDetail ? 35 : 11];
        exportHeader[0][this.isDetail ? 41 : 13] = exportHeader[0][this.isDetail ? 45 : 14];
        return exportHeader;
      },

      getExprotMerges() {
        return [
          { s: { r: 0, c: 0 }, e: { r: 1, c: 0 } },
          { s: { r: 0, c: 1 }, e: { r: 0, c: this.isDetail ? 10 : 3 } },
          {
            s: { r: 0, c: this.isDetail ? 11 : 4 },
            e: { r: 0, c: this.isDetail ? 20 : 6 },
          },
          {
            s: { r: 0, c: this.isDetail ? 21 : 7 },
            e: { r: 0, c: this.isDetail ? 30 : 9 },
          },
          {
            s: { r: 0, c: this.isDetail ? 31 : 10 },
            e: { r: 0, c: this.isDetail ? 40 : 12 },
          },
          {
            s: { r: 0, c: this.isDetail ? 41 : 13 },
            e: { r: 0, c: this.isDetail ? 50 : 15 },
          },
        ];
      },

      handleSearch() {
        this.fetchBaseInfo();
      },

      handleReset() {
        this.currentMonth = dayjs();
        this.currentWeek = 1;
        this.isDetail = false;
        this.fetchBaseInfo();
      },

      handleShowFilter() {
        this.showFilter = true;
      },

      handleSaveFilter(updatedFields) {
        this.selectedFields = updatedFields;
        this.searchFormOptions = updatedFields;

        // 更新表单显示
        const dateField = updatedFields.find((f) => f.value === 'date');
        const detailField = updatedFields.find((f) => f.value === 'week');

        // 根据选择的字段更新表单显示
        this.$nextTick(() => {
          const formWrapper = document.querySelector('.form-wrapper');
          if (formWrapper) {
            const dateItem = formWrapper.querySelector('.form-item:nth-child(1)');
            const detailItem = formWrapper.querySelector('.form-item:nth-child(2)');

            if (dateItem) {
              dateItem.style.display = dateField?.selected ? 'flex' : 'none';
            }
            if (detailItem) {
              detailItem.style.display = detailField?.selected ? 'flex' : 'none';
            }
          }
        });

        // 重新查询数据
        this.fetchBaseInfo();
      },

      colRender(val, record, m) {
        if (m.showFormatter) {
          const [methodName, ...params] = m.showFormatter.split('|');
          if (typeof this[methodName] === 'function') {
            return this[methodName](val, ...params);
          }
        }
        return val;
      },

      checkTag(key) {
        return key.includes('小计');
      },

      percentFormatter(value) {
        return (value * 100).toFixed(0) + '%';
      },

      percentTipFormatter(params) {
        return (
          params[0].axisValue +
          '<br />' +
          params
            .map((p) => {
              return `${p.marker} ${p.seriesName}: ${(p.data * 100).toFixed(0)}%`;
            })
            .join('<br />')
        );
      },

      currencyWFormatter(value, dot = 2, unit = '万') {
        return MathUtil.currencyWFormatter(value, dot, unit);
      },

      currencyWNFormatter(value, dot = 0) {
        return MathUtil.currencyWNFormatter(value, dot);
      },

      percent2DFormatter(value, dot = 2) {
        return MathUtil.percent2DFormatter(value, dot);
      },

      diffPercent2Formatter(thisData, lastData, dot = 2) {
        return MathUtil.diffPercent2Formatter(thisData, lastData, dot);
      },

      dot2Formatter(value, dot = 2) {
        return MathUtil.dot2Formatter(value, dot);
      },

      dateRangeFormatter(dataRange) {
        return DateUtil.dateRangeFormatter(dataRange);
      },

      dateFormatter(data) {
        return DateUtil.dateFormatter(data);
      },

      monthFormatter(data) {
        return DateUtil.monthFormatter(data);
      },

      safeDivide(numerator, denominator) {
        return MathUtil.safeDivide(numerator, denominator);
      },
    },
  };
</script>

<style lang="less" scoped>
  .main-frame-desktop-header {
    padding: 24px;
    background: #fff;
    margin-bottom: 16px;
  }

  .top-section {
    background: #fff;
    padding: 24px 24px 0;
  }

  .header-wrapper {
    margin-bottom: 24px;

    .title {
      font-size: 18px;
      font-weight: 600;
      color: #1a253b;
      margin: 0;
      padding: 0;
    }
  }

  .form-wrapper {
    margin-bottom: 24px;

    .form-content {
      display: flex;
      align-items: center;
    }

    .form-item {
      flex: 1;
      display: flex;
      align-items: center;
      padding: 0 16px;

      &:first-child {
        padding-left: 0;
        justify-content: flex-end;
      }

      &:last-child {
        padding-right: 0;
      }

      .label {
        margin-right: 12px;
        color: rgba(0, 0, 0, 0.85);
        font-size: 14px;
      }
    }
    .form-item-center {
      justify-content: center;
    }
    .filter-icon-container {
      display: inline-block;
      padding: 4px;
      border-radius: 4px;
      transition: all 0.3s ease;
      margin-left: 10px;
    }

    .icon-screen {
      width: 20px;
      height: 20px;
      cursor: pointer;
      transition: all 0.3s ease;
      object-fit: scale-down;
    }

    .filter-icon-container:hover {
      background-color: #e1ebf9;
    }

    .icon-screen:hover {
      transform: scale(1.1);
      opacity: 0.8;
    }
  }

  .main-content {
    flex: 1;
    background: @content-inside-bg;
    padding: 16px 0;
    overflow: hidden;

    .card-flex-all {
      height: 100%;
    }

    &-title-custom {
      color: #00b578 !important;
      font-weight: 500;
    }
  }

  .card-flex-all {
    margin-bottom: 24px;
  }
  @media @desktop {
    .top-content {
      display: flex;
    }
    .card-flex-all {
      flex: 1 1 calc(100% - 10px);
    }
    .card-flex {
      flex: 1 1 calc(50% - 10px);
    }
  }

  ::v-deep .ant-table-summary {
    background: #e7f1fd;
    position: sticky;
    bottom: 0;
    z-index: 2;
    td {
      border-bottom: none !important;
      padding: 12px 8px !important;
      text-align: right;
    }
    td:first-child {
      text-align: left;
      background: #e7f1fd !important;
    }
  }

  ::v-deep .ant-table-cell-fix-left {
    background: #e7f1fd !important;
  }

  ::v-deep .ant-table-summary > tr > td.ant-table-cell-fix-left {
    background: #e7f1fd !important;
  }

  ::v-deep .ant-table-tbody {
    tr.ant-table-row {
      td {
        &:first-child {
          .main-content-title-custom {
            color: #00b578 !important;
          }
        }
      }
    }
  }
</style>
